Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 388
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 4208
0.00% covered (danger)
0.00%
0 / 18
CRAP
0.00% covered (danger)
0.00%
0 / 1
PKPContextService
0.00% covered (danger)
0.00%
0 / 388
0.00% covered (danger)
0.00%
0 / 122
0.00% covered (danger)
0.00%
0 / 4208
0.00% covered (danger)
0.00%
0 / 18
9702
0.00% covered (danger)
0.00%
0 / 1
 get
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCount
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getIds
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getManySummary
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getMany
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 getMax
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 getQueryBuilder
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getProperties
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
56
 getSummaryProperties
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFullProperties
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 116
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
1640
 add
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4096
0.00% covered (danger)
0.00%
0 / 1
210
 edit
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
56
 delete
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 restoreLocaleDefaults
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 moveTemporaryFile
0.00% covered (danger)
0.00%
0 / 18
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
20
 exists
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 _saveFileParam
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2/**
3 * @file classes/services/PKPContextService.php
4 *
5 * Copyright (c) 2014-2021 Simon Fraser University
6 * Copyright (c) 2000-2021 John Willinsky
7 * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
8 *
9 * @class PKPContextService
10 *
11 * @ingroup services
12 *
13 * @brief Helper class that encapsulates business logic for contexts (journals
14 *  and presses)
15 */
16
17namespace PKP\services;
18
19use APP\core\Application;
20use APP\core\Request;
21use APP\facades\Repo;
22use APP\file\PublicFileManager;
23use APP\services\queryBuilders\ContextQueryBuilder;
24use PKP\announcement\AnnouncementTypeDAO;
25use PKP\context\Context;
26use PKP\context\ContextDAO;
27use PKP\core\Core;
28use PKP\core\PKPApplication;
29use PKP\db\DAORegistry;
30use PKP\db\DAOResultFactory;
31use PKP\db\DAOResultIterator;
32use PKP\db\DBResultRange;
33use PKP\facades\Locale;
34use PKP\file\ContextFileManager;
35use PKP\file\FileManager;
36use PKP\file\TemporaryFile;
37use PKP\file\TemporaryFileManager;
38use PKP\navigationMenu\NavigationMenuDAO;
39use PKP\navigationMenu\NavigationMenuItemDAO;
40use PKP\plugins\Hook;
41use PKP\plugins\PluginRegistry;
42use PKP\plugins\PluginSettingsDAO;
43use PKP\reviewForm\ReviewFormDAO;
44use PKP\security\Role;
45use PKP\security\RoleDAO;
46use PKP\services\interfaces\EntityPropertyInterface;
47use PKP\services\interfaces\EntityReadInterface;
48use PKP\services\interfaces\EntityWriteInterface;
49use PKP\submission\GenreDAO;
50use PKP\validation\ValidatorFactory;
51
52abstract class PKPContextService implements EntityPropertyInterface, EntityReadInterface, EntityWriteInterface
53{
54    /**
55     * @var array List of file directories to create on installation. Use %d to
56     *  use the context ID in a file path.
57     */
58    public $installFileDirs;
59
60    /**
61     * @var array The file directory where context files are stored. Expects
62     *  `journals` or `presses`.
63     */
64    public $contextsFileDirName;
65
66    /**
67     * @copydoc \PKP\services\interfaces\EntityReadInterface::get()
68     */
69    public function get($contextId)
70    {
71        return Application::getContextDAO()->getById($contextId);
72    }
73
74    /**
75     * @copydoc \PKP\services\interfaces\EntityReadInterface::getCount()
76     */
77    public function getCount($args = [])
78    {
79        return $this->getQueryBuilder($args)->getCount();
80    }
81
82    /**
83     * @copydoc \PKP\services\interfaces\EntityReadInterface::getIds()
84     */
85    public function getIds($args = [])
86    {
87        return $this->getQueryBuilder($args)->getIds();
88    }
89
90    /**
91     * Get a summary of context information limited, filtered
92     * and sorted by $args.
93     *
94     * This is faster than getMany if you don't need to
95     * retrieve all the context settings. It returns the
96     * data from the main table and the name of the context
97     * in its primary locale.
98     *
99     * @see self::getMany()
100     *
101     * @return array
102     */
103    public function getManySummary($args = [])
104    {
105        return $this->getQueryBuilder($args)->getManySummary();
106    }
107
108    /**
109     * Get a collection of Context objects limited, filtered
110     * and sorted by $args
111     *
112     * @param array $args {
113     *
114     *         @option bool isEnabled
115     *         @option int userId
116     *         @option string searchPhrase
117     *         @option int count
118     *         @option int offset
119     * }
120     *
121     * @return DAOResultIterator<Context>
122     */
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
127            $range = new DBResultRange($args['count'], null, $args['offset'] ?? 0);
128        }
129        // Pagination is handled by the DAO, so don't pass count and offset
130        // arguments to the QueryBuilder.
131        if (isset($args['count'])) {
132            unset($args['count']);
133        }
134        if (isset($args['offset'])) {
135            unset($args['offset']);
136        }
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
144
145    /**
146     * @copydoc \PKP\services\interfaces\EntityReadInterface::getMax()
147     */
148    public function getMax($args = [])
149    {
150        // Don't accept args to limit the results
151        if (isset($args['count'])) {
152            unset($args['count']);
153        }
154        if (isset($args['offset'])) {
155            unset($args['offset']);
156        }
157        return $this->getQueryBuilder($args)->getCount();
158    }
159
160    /**
161     * @copydoc \PKP\services\interfaces\EntityReadInterface::getQueryBuilder()
162     *
163     * @return ContextQueryBuilder
164     *
165     * @hook Context::getMany::queryBuilder [[&$contextListQB, $args]]
166     */
167    public function getQueryBuilder($args = [])
168    {
169        $defaultArgs = [
170            'isEnabled' => null,
171            'userId' => null,
172            'searchPhrase' => null,
173        ];
174
175        $args = array_merge($defaultArgs, $args);
176
177        $contextListQB = new ContextQueryBuilder();
178        $contextListQB
179            ->filterByIsEnabled($args['isEnabled'])
180            ->filterByUserId($args['userId'])
181            ->searchPhrase($args['searchPhrase']);
182
183        Hook::call('Context::getMany::queryBuilder', [&$contextListQB, $args]);
184
185        return $contextListQB;
186    }
187
188    /**
189     * @copydoc \PKP\services\interfaces\EntityPropertyInterface::getProperties()
190     *
191     * @param null|mixed $args
192     *
193     * @hook Context::getProperties [[&$values, $context, $props, $args]]
194     */
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
238
239    /**
240     * @copydoc \PKP\services\interfaces\EntityPropertyInterface::getSummaryProperties()
241     *
242     * @param null|mixed $args
243     */
244    public function getSummaryProperties($context, $args = null)
245    {
246        $props = app()->get('schema')->getSummaryProps(PKPSchemaService::SCHEMA_CONTEXT);
247
248        return $this->getProperties($context, $props, $args);
249    }
250
251    /**
252     * @copydoc \PKP\services\interfaces\EntityPropertyInterface::getFullProperties()
253     *
254     * @param null|mixed $args
255     */
256    public function getFullProperties($context, $args = null)
257    {
258        $props = app()->get('schema')->getFullProps(PKPSchemaService::SCHEMA_CONTEXT);
259
260        return $this->getProperties($context, $props, $args);
261    }
262
263    /**
264     * @copydoc \PKP\services\entityProperties\EntityWriteInterface::validate()
265     *
266     * @hook Context::validate [[&$errors, $action, $props, $allowedLocales, $primaryLocale]]
267     */
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
451
452    /**
453     * @copydoc \PKP\services\entityProperties\EntityWriteInterface::add()
454     *
455     * @hook Context::defaults::localeParams [[&$localeParams, $context, $request]]
456     * @hook Context::add [[&$context, $request]]
457     */
458    public function add($context, $request)
459    {
460        $site = $request->getSite();
461        $currentUser = $request->getUser();
462        $contextDao = Application::getContextDAO();
463
464        if (!$context->getData('primaryLocale')) {
465            $context->setData('primaryLocale', $site->getPrimaryLocale());
466        }
467        if (!$context->getData('supportedLocales')) {
468            $context->setData('supportedLocales', $site->getSupportedLocales());
469        }
470
471        // Specify values needed to render default locale strings
472        $localeParams = [
473            'submissionGuidelinesUrl' => $request->getDispatcher()->url(
474                $request,
475                Application::ROUTE_PAGE,
476                $context->getPath(),
477                'about',
478                'submissions'
479            ),
480            'indexUrl' => $request->getIndexUrl(),
481            'primaryLocale' => $context->getData('primaryLocale'),
482            'contextName' => $context->getData('name', $context->getPrimaryLocale()),
483            'contextPath' => $context->getData('urlPath'),
484            'contextUrl' => $request->getDispatcher()->url(
485                $request,
486                PKPApplication::ROUTE_PAGE,
487                $context->getPath()
488            ),
489        ];
490
491        // Allow plugins to extend the $localeParams for new property defaults
492        Hook::call('Context::defaults::localeParams', [&$localeParams, $context, $request]);
493
494        $context = app()->get('schema')->setDefaults(
495            PKPSchemaService::SCHEMA_CONTEXT,
496            $context,
497            $context->getData('supportedLocales'),
498            $context->getData('primaryLocale'),
499            $localeParams
500        );
501
502        if (!$context->getData('supportedFormLocales')) {
503            $context->setData('supportedFormLocales', [$context->getData('primaryLocale')]);
504        }
505        if (!$context->getData('supportedDefaultSubmissionLocale')) {
506            $context->setData('supportedDefaultSubmissionLocale', $context->getData('primaryLocale'));
507        }
508        if (!$context->getData('supportedAddedSubmissionLocales')) {
509            $context->setData('supportedAddedSubmissionLocales', [$context->getData('supportedDefaultSubmissionLocale')]);
510        }
511        if (!$context->getData('supportedSubmissionLocales')) {
512            $context->setData('supportedSubmissionLocales', [$context->getData('supportedDefaultSubmissionLocale')]);
513        }
514        if (!$context->getData('supportedSubmissionMetadataLocales')) {
515            $context->setData('supportedSubmissionMetadataLocales', [$context->getData('supportedDefaultSubmissionLocale')]);
516        }
517
518        $context->setSequence(REALLY_BIG_NUMBER);
519        $contextDao->insertObject($context);
520        $contextDao->resequence();
521
522        $context = $this->get($context->getId());
523
524        // Move uploaded files into place and update the settings
525        $supportedLocales = $context->getSupportedFormLocales();
526        $fileUploadProps = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
527        $params = [];
528        foreach ($fileUploadProps as $fileUploadProp) {
529            $value = $context->getData($fileUploadProp);
530            if (empty($value)) {
531                continue;
532            }
533            foreach ($supportedLocales as $localeKey) {
534                if (!array_key_exists($localeKey, $value)) {
535                    continue;
536                }
537                $value[$localeKey] = $this->_saveFileParam($context, $value[$localeKey], $fileUploadProp, $currentUser->getId(), $localeKey, true);
538            }
539            $params[$fileUploadProp] = $value;
540        }
541        if (!empty($params['styleSheet'])) {
542            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $currentUser->getId());
543        }
544        $context = $this->edit($context, $params, $request);
545
546        $genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
547        $genreDao->installDefaults($context->getId(), $context->getData('supportedLocales'));
548
549        Repo::userGroup()->installSettings($context->getId(), 'registry/userGroups.xml');
550
551        $managerUserGroup = Repo::userGroup()->getByRoleIds([Role::ROLE_ID_MANAGER], $context->getId(), true)->firstOrFail();
552        Repo::userGroup()->assignUserToGroup($currentUser->getId(), $managerUserGroup->getId());
553
554        $fileManager = new FileManager();
555        foreach ($this->installFileDirs as $dir) {
556            $fileManager->mkdir(sprintf($dir, $this->contextsFileDirName, $context->getId()));
557        }
558
559        $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /** @var NavigationMenuDAO $navigationMenuDao */
560        $navigationMenuDao->installSettings($context->getId(), 'registry/navigationMenus.xml');
561
562        Repo::emailTemplate()->dao->installAlternateEmailTemplates($context->getId());
563
564        // Load all plugins so they can hook in and add their installation settings
565        PluginRegistry::loadAllPlugins();
566
567        Hook::call('Context::add', [&$context, $request]);
568
569        return $context;
570    }
571
572    /**
573     * @copydoc \PKP\services\entityProperties\EntityWriteInterface::edit()
574     *
575     * @hook Context::edit [[&$newContext, $context, $params, $request]]
576     */
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
610
611    /**
612     * @copydoc \PKP\services\entityProperties\EntityWriteInterface::delete()
613     *
614     * @hook Context::delete::before [[&$context]]
615     */
616    public function delete($context)
617    {
618        Hook::call('Context::delete::before', [&$context]);
619
620        $announcementTypeDao = DAORegistry::getDAO('AnnouncementTypeDAO'); /** @var AnnouncementTypeDAO $announcementTypeDao */
621        $announcementTypeDao->deleteByContextId($context->getId());
622
623        Repo::reviewAssignment()->deleteByContextId($context->getId());
624
625        Repo::userGroup()->deleteByContextId($context->getId());
626
627        $genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
628        $genreDao->deleteByContextId($context->getId());
629
630        Repo::announcement()->deleteMany(
631            Repo::announcement()
632                ->getCollector()
633                ->filterByContextIds([$context->getId()])
634        );
635
636        Repo::highlight()
637            ->getCollector()
638            ->filterByContextIds([$context->getId()])
639            ->deleteMany();
640
641        Repo::institution()->deleteMany(
642            Repo::institution()
643                ->getCollector()
644                ->filterByContextIds([$context->getId()])
645        );
646
647        Repo::emailTemplate()->restoreDefaults($context->getId());
648
649        $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */
650        $pluginSettingsDao->deleteByContextId($context->getId());
651
652        $reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */
653        $reviewFormDao->deleteByAssoc($context->getAssocType(), $context->getId());
654
655        $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /** @var NavigationMenuDAO $navigationMenuDao */
656        $navigationMenuDao->deleteByContextId($context->getId());
657
658        $navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO'); /** @var NavigationMenuItemDAO $navigationMenuItemDao */
659        $navigationMenuItemDao->deleteByContextId($context->getId());
660
661        $contextFileManager = new ContextFileManager($context->getId());
662        $contextFileManager->rmtree($contextFileManager->getBasePath());
663
664        $contextDao = Application::getContextDao();
665        $contextDao->deleteObject($context);
666
667        Hook::call('Context::delete', [&$context]);
668    }
669
670    /**
671     * Restore default values for context settings in a specific local
672     *
673     * Updates multilingual values of a context, restoring default values in a
674     * specific context. This may be useful when a new language has been added
675     * after a context has been created, or when translations change and a journal
676     * wants to take advantage of the new values.
677     *
678     * @param Context $context The context to restore default values for
679     * @param Request $request
680     * @param string $locale Locale key to restore defaults for. Example: `en`
681     *
682     * @hook Context::restoreLocaleDefaults::localeParams [[&$localeParams, $context, $request, $locale]]
683     */
684    public function restoreLocaleDefaults($context, $request, $locale)
685    {
686        Locale::installLocale($locale);
687
688        // Specify values needed to render default locale strings
689        $localeParams = [
690            'indexUrl' => $request->getIndexUrl(),
691            'contextPath' => $context->getData('urlPath'),
692            'journalPath' => $context->getData('urlPath'), // DEPRECATED
693            'primaryLocale' => $context->getData('primaryLocale'),
694            'journalName' => $context->getData('name', $locale), // DEPRECATED
695            'contextName' => $context->getData('name', $locale),
696            'contextUrl' => $request->getDispatcher()->url(
697                $request,
698                PKPApplication::ROUTE_PAGE,
699                $context->getPath()
700            ),
701        ];
702
703        // Allow plugins to extend the $localeParams for new property defaults
704        Hook::call('Context::restoreLocaleDefaults::localeParams', [&$localeParams, $context, $request, $locale]);
705
706        $localeDefaults = app()->get('schema')->getLocaleDefaults(PKPSchemaService::SCHEMA_CONTEXT, $locale, $localeParams);
707
708        $params = [];
709        foreach ($localeDefaults as $paramName => $value) {
710            $params[$paramName] = array_merge(
711                (array) $context->getData($paramName),
712                [$locale => $localeDefaults[$paramName]]
713            );
714        }
715
716        return $this->edit($context, $params, $request);
717    }
718
719    /**
720     * Move a temporary file to the context's public directory
721     *
722     * @param Context $context
723     * @param TemporaryFile $temporaryFile
724     * @param string $fileNameBase Unique identifier to use for the filename. The
725     *  Extension and locale will be appended.
726     * @param int $userId ID of the user who uploaded the temporary file
727     * @param string $localeKey Example: en. Leave empty for a file that is
728     *  not localized.
729     *
730     * @return string|boolean The new filename or false on failure
731     */
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
739            $fileName .= '_' . $localeKey;
740        }
741
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
744            $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
745        }
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
755            return false;
756        }
757
758        $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
759
760        return $fileName;
761    }
762
763    /**
764     * Checks if a context exists
765     */
766    public function exists(int $id): bool
767    {
768        /** @var ContextDAO $contextDao */
769        $contextDao = Application::getContextDao();
770        return $contextDao->exists($id);
771    }
772
773    /**
774     * Handle a context setting for an uploaded file
775     *
776     * - Moves the temporary file to the public directory
777     * - Resets the param value to what is expected to be stored in the db
778     * - If a null value is passed, deletes any existing file
779     *
780     * This method is protected because all operations which edit contexts should
781     * go through the add and edit methods in order to ensure that
782     * the appropriate hooks are fired.
783     *
784     * @param Context $context The context being edited
785     * @param mixed $value The param value to be saved. Contains the temporary
786     *  file ID if a new file has been uploaded.
787     * @param string $settingName The name of the setting to save, typically used
788     *  in the filename.
789     * @param int $userId ID of the user who owns the temporary file
790     * @param string $localeKey Optional. Used in the filename for multilingual
791     *  properties.
792     * @param bool $isImage Optional. For image files which return alt text,
793     *  width, height, etc in the param value.
794     *
795     * @return string|array|null New param value or null on failure
796     */
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
803            $setting = $context->getData($settingName, $localeKey);
804            if ($setting) {
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
806                $publicFileManager = new PublicFileManager();
807                $publicFileManager->removeContextFile($context->getId(), $fileName);
808            }
809            return null;
810        }
811
812        // Check if there is something to upload
813        if (empty($value['temporaryFileId'])) {
814            return $value;
815        }
816
817        $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
818        $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
819
820        if ($fileName) {
821            // Get the details for image uploads
822            if ($isImage) {
823                $publicFileManager = new PublicFileManager();
824
825                $filePath = $publicFileManager->getContextFilesPath($context->getId());
826                [$width, $height] = getimagesize($filePath . '/' . $fileName);
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
828
829                return [
830                    'name' => $temporaryFile->getOriginalFileName(),
831                    'uploadName' => $fileName,
832                    'width' => $width,
833                    'height' => $height,
834                    'dateUploaded' => Core::getCurrentDate(),
835                    'altText' => $altText,
836                ];
837            } else {
838                return [
839                    'name' => $temporaryFile->getOriginalFileName(),
840                    'uploadName' => $fileName,
841                    'dateUploaded' => Core::getCurrentDate(),
842                ];
843            }
844        }
845
846        return false;
847    }
848}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

PKP\services\
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
 
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
PKPContextService->_saveFileParam
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
803            $setting = $context->getData($settingName, $localeKey);
804            if ($setting) {
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
806                $publicFileManager = new PublicFileManager();
807                $publicFileManager->removeContextFile($context->getId(), $fileName);
808            }
809            return null;
 
809            return null;
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
803            $setting = $context->getData($settingName, $localeKey);
804            if ($setting) {
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
 
805                $fileName = $isImage ? $setting['uploadName'] : $setting;
806                $publicFileManager = new PublicFileManager();
807                $publicFileManager->removeContextFile($context->getId(), $fileName);
808            }
809            return null;
 
809            return null;
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
803            $setting = $context->getData($settingName, $localeKey);
804            if ($setting) {
 
809            return null;
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
813        if (empty($value['temporaryFileId'])) {
 
814            return $value;
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
813        if (empty($value['temporaryFileId'])) {
 
817        $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
818        $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
819
820        if ($fileName) {
 
822            if ($isImage) {
 
823                $publicFileManager = new PublicFileManager();
824
825                $filePath = $publicFileManager->getContextFilesPath($context->getId());
826                [$width, $height] = getimagesize($filePath . '/' . $fileName);
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
 
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
 
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
828
829                return [
830                    'name' => $temporaryFile->getOriginalFileName(),
831                    'uploadName' => $fileName,
832                    'width' => $width,
833                    'height' => $height,
834                    'dateUploaded' => Core::getCurrentDate(),
835                    'altText' => $altText,
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
813        if (empty($value['temporaryFileId'])) {
 
817        $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
818        $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
819
820        if ($fileName) {
 
822            if ($isImage) {
 
823                $publicFileManager = new PublicFileManager();
824
825                $filePath = $publicFileManager->getContextFilesPath($context->getId());
826                [$width, $height] = getimagesize($filePath . '/' . $fileName);
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
 
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
 
827                $altText = !empty($value['altText']) ? $value['altText'] : '';
828
829                return [
830                    'name' => $temporaryFile->getOriginalFileName(),
831                    'uploadName' => $fileName,
832                    'width' => $width,
833                    'height' => $height,
834                    'dateUploaded' => Core::getCurrentDate(),
835                    'altText' => $altText,
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
813        if (empty($value['temporaryFileId'])) {
 
817        $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
818        $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
819
820        if ($fileName) {
 
822            if ($isImage) {
 
839                    'name' => $temporaryFile->getOriginalFileName(),
840                    'uploadName' => $fileName,
841                    'dateUploaded' => Core::getCurrentDate(),
797    protected function _saveFileParam($context, $value, $settingName, $userId, $localeKey = '', $isImage = false)
798    {
799        $temporaryFileManager = new TemporaryFileManager();
800
801        // If the value is null, clean up any existing file in the system
802        if (is_null($value)) {
 
813        if (empty($value['temporaryFileId'])) {
 
817        $temporaryFile = $temporaryFileManager->getFile((int) $value['temporaryFileId'], $userId);
818        $fileName = $this->moveTemporaryFile($context, $temporaryFile, $settingName, $userId, $localeKey);
819
820        if ($fileName) {
 
846        return false;
847    }
PKPContextService->delete
616    public function delete($context)
617    {
618        Hook::call('Context::delete::before', [&$context]);
619
620        $announcementTypeDao = DAORegistry::getDAO('AnnouncementTypeDAO'); /** @var AnnouncementTypeDAO $announcementTypeDao */
621        $announcementTypeDao->deleteByContextId($context->getId());
622
623        Repo::reviewAssignment()->deleteByContextId($context->getId());
624
625        Repo::userGroup()->deleteByContextId($context->getId());
626
627        $genreDao = DAORegistry::getDAO('GenreDAO'); /** @var GenreDAO $genreDao */
628        $genreDao->deleteByContextId($context->getId());
629
630        Repo::announcement()->deleteMany(
631            Repo::announcement()
632                ->getCollector()
633                ->filterByContextIds([$context->getId()])
634        );
635
636        Repo::highlight()
637            ->getCollector()
638            ->filterByContextIds([$context->getId()])
639            ->deleteMany();
640
641        Repo::institution()->deleteMany(
642            Repo::institution()
643                ->getCollector()
644                ->filterByContextIds([$context->getId()])
645        );
646
647        Repo::emailTemplate()->restoreDefaults($context->getId());
648
649        $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */
650        $pluginSettingsDao->deleteByContextId($context->getId());
651
652        $reviewFormDao = DAORegistry::getDAO('ReviewFormDAO'); /** @var ReviewFormDAO $reviewFormDao */
653        $reviewFormDao->deleteByAssoc($context->getAssocType(), $context->getId());
654
655        $navigationMenuDao = DAORegistry::getDAO('NavigationMenuDAO'); /** @var NavigationMenuDAO $navigationMenuDao */
656        $navigationMenuDao->deleteByContextId($context->getId());
657
658        $navigationMenuItemDao = DAORegistry::getDAO('NavigationMenuItemDAO'); /** @var NavigationMenuItemDAO $navigationMenuItemDao */
659        $navigationMenuItemDao->deleteByContextId($context->getId());
660
661        $contextFileManager = new ContextFileManager($context->getId());
662        $contextFileManager->rmtree($contextFileManager->getBasePath());
663
664        $contextDao = Application::getContextDao();
665        $contextDao->deleteObject($context);
666
667        Hook::call('Context::delete', [&$context]);
668    }
PKPContextService->edit
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
587                continue;
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
587                continue;
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
591                    continue;
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
591                    continue;
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
587                continue;
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
587                continue;
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
591                    continue;
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
591                    continue;
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
 
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
586            if (!array_key_exists($fileUploadParam, $params)) {
 
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
597            $params['styleSheet'] = $this->_saveFileParam($context, $params['styleSheet'], 'styleSheet', $userId);
598        }
599
600        $newContext = $contextDao->newDataObject();
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
577    public function edit($context, $params, $request)
578    {
579        $contextDao = Application::getContextDao();
580
581        // Move uploaded files into place and update the params
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
 
582        $userId = $request->getUser() ? $request->getUser()->getId() : null;
583        $supportedLocales = $context->getSupportedFormLocales();
584        $fileUploadParams = ['favicon', 'homepageImage', 'pageHeaderLogoImage'];
585        foreach ($fileUploadParams as $fileUploadParam) {
 
585        foreach ($fileUploadParams as $fileUploadParam) {
586            if (!array_key_exists($fileUploadParam, $params)) {
587                continue;
588            }
589            foreach ($supportedLocales as $localeKey) {
590                if (!array_key_exists($localeKey, $params[$fileUploadParam])) {
591                    continue;
592                }
593                $params[$fileUploadParam][$localeKey] = $this->_saveFileParam($context, $params[$fileUploadParam][$localeKey], $fileUploadParam, $userId, $localeKey, true);
594            }
595        }
596        if (array_key_exists('styleSheet', $params)) {
 
600        $newContext = $contextDao->newDataObject();
601        $newContext->_data = array_merge($context->_data, $params);
602
603        Hook::call('Context::edit', [&$newContext, $context, $params, $request]);
604
605        $contextDao->updateObject($newContext);
606        $newContext = $this->get($newContext->getId());
607
608        return $newContext;
609    }
PKPContextService->exists
766    public function exists(int $id): bool
767    {
768        /** @var ContextDAO $contextDao */
769        $contextDao = Application::getContextDao();
770        return $contextDao->exists($id);
771    }
PKPContextService->get
69    public function get($contextId)
70    {
71        return Application::getContextDAO()->getById($contextId);
72    }
PKPContextService->getCount
77    public function getCount($args = [])
78    {
79        return $this->getQueryBuilder($args)->getCount();
80    }
PKPContextService->getFullProperties
256    public function getFullProperties($context, $args = null)
257    {
258        $props = app()->get('schema')->getFullProps(PKPSchemaService::SCHEMA_CONTEXT);
259
260        return $this->getProperties($context, $props, $args);
261    }
PKPContextService->getIds
85    public function getIds($args = [])
86    {
87        return $this->getQueryBuilder($args)->getIds();
88    }
PKPContextService->getMany
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
127            $range = new DBResultRange($args['count'], null, $args['offset'] ?? 0);
128        }
129        // Pagination is handled by the DAO, so don't pass count and offset
130        // arguments to the QueryBuilder.
131        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
132            unset($args['count']);
133        }
134        if (isset($args['offset'])) {
 
134        if (isset($args['offset'])) {
 
135            unset($args['offset']);
136        }
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
127            $range = new DBResultRange($args['count'], null, $args['offset'] ?? 0);
128        }
129        // Pagination is handled by the DAO, so don't pass count and offset
130        // arguments to the QueryBuilder.
131        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
132            unset($args['count']);
133        }
134        if (isset($args['offset'])) {
 
134        if (isset($args['offset'])) {
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
127            $range = new DBResultRange($args['count'], null, $args['offset'] ?? 0);
128        }
129        // Pagination is handled by the DAO, so don't pass count and offset
130        // arguments to the QueryBuilder.
131        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
134        if (isset($args['offset'])) {
 
135            unset($args['offset']);
136        }
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
127            $range = new DBResultRange($args['count'], null, $args['offset'] ?? 0);
128        }
129        // Pagination is handled by the DAO, so don't pass count and offset
130        // arguments to the QueryBuilder.
131        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
134        if (isset($args['offset'])) {
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
132            unset($args['count']);
133        }
134        if (isset($args['offset'])) {
 
134        if (isset($args['offset'])) {
 
135            unset($args['offset']);
136        }
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
132            unset($args['count']);
133        }
134        if (isset($args['offset'])) {
 
134        if (isset($args['offset'])) {
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
134        if (isset($args['offset'])) {
 
135            unset($args['offset']);
136        }
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
123    public function getMany($args = [])
124    {
125        $range = null;
126        if (isset($args['count'])) {
 
131        if (isset($args['count'])) {
 
134        if (isset($args['offset'])) {
 
137        $contextListQO = $this->getQueryBuilder($args)->getQuery();
138        $contextDao = Application::getContextDAO();
139        $result = $contextDao->retrieveRange($contextListQO->toSql(), $contextListQO->getBindings(), $range);
140        $queryResults = new DAOResultFactory($result, $contextDao, '_fromRow');
141
142        return $queryResults->toIterator();
143    }
PKPContextService->getManySummary
103    public function getManySummary($args = [])
104    {
105        return $this->getQueryBuilder($args)->getManySummary();
106    }
PKPContextService->getMax
148    public function getMax($args = [])
149    {
150        // Don't accept args to limit the results
151        if (isset($args['count'])) {
 
152            unset($args['count']);
153        }
154        if (isset($args['offset'])) {
 
154        if (isset($args['offset'])) {
 
155            unset($args['offset']);
156        }
157        return $this->getQueryBuilder($args)->getCount();
 
157        return $this->getQueryBuilder($args)->getCount();
158    }
148    public function getMax($args = [])
149    {
150        // Don't accept args to limit the results
151        if (isset($args['count'])) {
 
152            unset($args['count']);
153        }
154        if (isset($args['offset'])) {
 
154        if (isset($args['offset'])) {
 
157        return $this->getQueryBuilder($args)->getCount();
158    }
148    public function getMax($args = [])
149    {
150        // Don't accept args to limit the results
151        if (isset($args['count'])) {
 
154        if (isset($args['offset'])) {
 
155            unset($args['offset']);
156        }
157        return $this->getQueryBuilder($args)->getCount();
 
157        return $this->getQueryBuilder($args)->getCount();
158    }
148    public function getMax($args = [])
149    {
150        // Don't accept args to limit the results
151        if (isset($args['count'])) {
 
154        if (isset($args['offset'])) {
 
157        return $this->getQueryBuilder($args)->getCount();
158    }
PKPContextService->getProperties
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
212                case '_href':
 
224                    $values[$prop] = $context->getData($prop);
225                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
212                case '_href':
 
224                    $values[$prop] = $context->getData($prop);
225                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
 
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
 
222                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
 
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
 
222                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
 
222                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
212                case '_href':
 
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
 
222                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
205                case 'url':
 
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
195    public function getProperties($context, $props, $args = null)
196    {
197        $apiRequest = $args['apiRequest'] ?? '';
198        $request = $args['request'];
199        $dispatcher = $request->getDispatcher();
200
201        $values = [];
202
203        foreach ($props as $prop) {
 
203        foreach ($props as $prop) {
204            switch ($prop) {
205                case 'url':
206                    $values[$prop] = $dispatcher->url(
207                        $request,
208                        PKPApplication::ROUTE_PAGE,
209                        $context->getPath()
210                    );
211                    break;
212                case '_href':
213                    $values[$prop] = null;
214                    if (!empty($apiRequest)) {
215                        $values[$prop] = $dispatcher->url(
216                            $args['request'],
217                            PKPApplication::ROUTE_API,
218                            $context->getData('urlPath'),
219                            'contexts/' . $context->getId()
220                        );
221                    }
222                    break;
223                default:
224                    $values[$prop] = $context->getData($prop);
225                    break;
226            }
227        }
228
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
 
229        $supportedLocales = empty($args['supportedLocales']) ? $context->getSupportedFormLocales() : $args['supportedLocales'];
230        $values = app()->get('schema')->addMissingMultilingualValues(PKPSchemaService::SCHEMA_CONTEXT, $values, $supportedLocales);
231
232        Hook::call('Context::getProperties', [&$values, $context, $props, $args]);
233
234        ksort($values);
235
236        return $values;
237    }
PKPContextService->getQueryBuilder
167    public function getQueryBuilder($args = [])
168    {
169        $defaultArgs = [
170            'isEnabled' => null,
171            'userId' => null,
172            'searchPhrase' => null,
173        ];
174
175        $args = array_merge($defaultArgs, $args);
176
177        $contextListQB = new ContextQueryBuilder();
178        $contextListQB
179            ->filterByIsEnabled($args['isEnabled'])
180            ->filterByUserId($args['userId'])
181            ->searchPhrase($args['searchPhrase']);
182
183        Hook::call('Context::getMany::queryBuilder', [&$contextListQB, $args]);
184
185        return $contextListQB;
186    }
PKPContextService->getSummaryProperties
244    public function getSummaryProperties($context, $args = null)
245    {
246        $props = app()->get('schema')->getSummaryProps(PKPSchemaService::SCHEMA_CONTEXT);
247
248        return $this->getProperties($context, $props, $args);
249    }
PKPContextService->moveTemporaryFile
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
739            $fileName .= '_' . $localeKey;
740        }
741
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
744            $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
745        }
746        $fileName .= $extension;
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
755            return false;
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
739            $fileName .= '_' . $localeKey;
740        }
741
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
744            $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
745        }
746        $fileName .= $extension;
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
758        $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
759
760        return $fileName;
761    }
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
739            $fileName .= '_' . $localeKey;
740        }
741
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
755            return false;
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
739            $fileName .= '_' . $localeKey;
740        }
741
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
758        $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
759
760        return $fileName;
761    }
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
744            $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
745        }
746        $fileName .= $extension;
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
755            return false;
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
744            $extension = $publicFileManager->getImageExtension($temporaryFile->getFileType());
745        }
746        $fileName .= $extension;
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
758        $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
759
760        return $fileName;
761    }
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
755            return false;
732    public function moveTemporaryFile($context, $temporaryFile, $fileNameBase, $userId, $localeKey = '')
733    {
734        $publicFileManager = new PublicFileManager();
735        $temporaryFileManager = new TemporaryFileManager();
736
737        $fileName = $fileNameBase;
738        if ($localeKey) {
 
742        $extension = $publicFileManager->getDocumentExtension($temporaryFile->getFileType());
743        if (!$extension) {
 
746        $fileName .= $extension;
747
748        $result = $publicFileManager->copyContextFile(
749            $context->getId(),
750            $temporaryFile->getFilePath(),
751            $fileName
752        );
753
754        if (!$result) {
 
758        $temporaryFileManager->deleteById($temporaryFile->getId(), $userId);
759
760        return $fileName;
761    }
PKPContextService->restoreLocaleDefaults
684    public function restoreLocaleDefaults($context, $request, $locale)
685    {
686        Locale::installLocale($locale);
687
688        // Specify values needed to render default locale strings
689        $localeParams = [
690            'indexUrl' => $request->getIndexUrl(),
691            'contextPath' => $context->getData('urlPath'),
692            'journalPath' => $context->getData('urlPath'), // DEPRECATED
693            'primaryLocale' => $context->getData('primaryLocale'),
694            'journalName' => $context->getData('name', $locale), // DEPRECATED
695            'contextName' => $context->getData('name', $locale),
696            'contextUrl' => $request->getDispatcher()->url(
697                $request,
698                PKPApplication::ROUTE_PAGE,
699                $context->getPath()
700            ),
701        ];
702
703        // Allow plugins to extend the $localeParams for new property defaults
704        Hook::call('Context::restoreLocaleDefaults::localeParams', [&$localeParams, $context, $request, $locale]);
705
706        $localeDefaults = app()->get('schema')->getLocaleDefaults(PKPSchemaService::SCHEMA_CONTEXT, $locale, $localeParams);
707
708        $params = [];
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
710            $params[$paramName] = array_merge(
711                (array) $context->getData($paramName),
712                [$locale => $localeDefaults[$paramName]]
713            );
714        }
715
716        return $this->edit($context, $params, $request);
717    }
684    public function restoreLocaleDefaults($context, $request, $locale)
685    {
686        Locale::installLocale($locale);
687
688        // Specify values needed to render default locale strings
689        $localeParams = [
690            'indexUrl' => $request->getIndexUrl(),
691            'contextPath' => $context->getData('urlPath'),
692            'journalPath' => $context->getData('urlPath'), // DEPRECATED
693            'primaryLocale' => $context->getData('primaryLocale'),
694            'journalName' => $context->getData('name', $locale), // DEPRECATED
695            'contextName' => $context->getData('name', $locale),
696            'contextUrl' => $request->getDispatcher()->url(
697                $request,
698                PKPApplication::ROUTE_PAGE,
699                $context->getPath()
700            ),
701        ];
702
703        // Allow plugins to extend the $localeParams for new property defaults
704        Hook::call('Context::restoreLocaleDefaults::localeParams', [&$localeParams, $context, $request, $locale]);
705
706        $localeDefaults = app()->get('schema')->getLocaleDefaults(PKPSchemaService::SCHEMA_CONTEXT, $locale, $localeParams);
707
708        $params = [];
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
710            $params[$paramName] = array_merge(
711                (array) $context->getData($paramName),
712                [$locale => $localeDefaults[$paramName]]
713            );
714        }
715
716        return $this->edit($context, $params, $request);
717    }
684    public function restoreLocaleDefaults($context, $request, $locale)
685    {
686        Locale::installLocale($locale);
687
688        // Specify values needed to render default locale strings
689        $localeParams = [
690            'indexUrl' => $request->getIndexUrl(),
691            'contextPath' => $context->getData('urlPath'),
692            'journalPath' => $context->getData('urlPath'), // DEPRECATED
693            'primaryLocale' => $context->getData('primaryLocale'),
694            'journalName' => $context->getData('name', $locale), // DEPRECATED
695            'contextName' => $context->getData('name', $locale),
696            'contextUrl' => $request->getDispatcher()->url(
697                $request,
698                PKPApplication::ROUTE_PAGE,
699                $context->getPath()
700            ),
701        ];
702
703        // Allow plugins to extend the $localeParams for new property defaults
704        Hook::call('Context::restoreLocaleDefaults::localeParams', [&$localeParams, $context, $request, $locale]);
705
706        $localeDefaults = app()->get('schema')->getLocaleDefaults(PKPSchemaService::SCHEMA_CONTEXT, $locale, $localeParams);
707
708        $params = [];
709        foreach ($localeDefaults as $paramName => $value) {
 
709        foreach ($localeDefaults as $paramName => $value) {
710            $params[$paramName] = array_merge(
711                (array) $context->getData($paramName),
712                [$locale => $localeDefaults[$paramName]]
713            );
714        }
715
716        return $this->edit($context, $params, $request);
717    }
PKPContextService->validate
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
422            $user = Application::get()->getRequest()->getUser();
423            $validator->after(function ($validator) use ($user) {
424                $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */
425                if (!$roleDao->userHasRole(PKPApplication::SITE_CONTEXT_ID, $user->getId(), Role::ROLE_ID_SITE_ADMIN)) {
426                    $validator->errors()->add('disableBulkEmailUserGroups', __('admin.settings.disableBulkEmailRoles.adminOnly'));
427                }
428            });
429        }
430
431        // Disallow empty DOI Prefix when enableDois is true
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
433            $context = Application::get()->getRequest()->getContext();
434            $validator->after(function ($validator) use ($context, $props) {
435                $enableDois = $props[Context::SETTING_ENABLE_DOIS] ?? $context->getData(Context::SETTING_ENABLE_DOIS);
436
437                if ($enableDois && empty($props[Context::SETTING_DOI_PREFIX])) {
438                    $validator->errors()->add(Context::SETTING_DOI_PREFIX, __('doi.manager.settings.doiPrefix.required'));
439                }
440            });
441        }
442
443        if ($validator->fails()) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
444            $errors = $schemaService->formatValidationErrors($validator->errors());
445        }
446
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }
268    public function validate($action, $props, $allowedLocales, $primaryLocale)
269    {
270        $schemaService = app()->get('schema'); /** @var PKPSchemaService $schemaService */
271
272        $validator = ValidatorFactory::make(
273            $props,
274            $schemaService->getValidationRules(PKPSchemaService::SCHEMA_CONTEXT, $allowedLocales),
275            [
276                'urlPath.regex' => __('admin.contexts.form.pathAlphaNumeric'),
277                'primaryLocale.regex' => __('validator.localeKey'),
278                'supportedDefaultSubmissionLocale.regex' => __('validator.localeKey'),
279                'supportedFormLocales.regex' => __('validator.localeKey'),
280                'supportedLocales.regex' => __('validator.localeKey'),
281                'supportedSubmissionLocales.*.regex' => __('validator.localeKey'),
282                'supportedSubmissionMetadataLocales.*.regex' => __('validator.localeKey'),
283            ]
284        );
285
286        // Check required fields
287        ValidatorFactory::required(
288            $validator,
289            $action,
290            $schemaService->getRequiredProps(PKPSchemaService::SCHEMA_CONTEXT),
291            $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT),
292            $allowedLocales,
293            $primaryLocale
294        );
295
296        // Check for input from disallowed locales
297        ValidatorFactory::allowedLocales($validator, $schemaService->getMultilingualProps(PKPSchemaService::SCHEMA_CONTEXT), $allowedLocales);
298
299        // Ensure that a urlPath, if provided, does not already exist
300        $validator->after(function ($validator) use ($action, $props) {
301            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath')) {
302                $contextDao = Application::getContextDAO();
303                $contextWithPath = $contextDao->getByPath($props['urlPath']);
304                if ($contextWithPath) {
305                    if (!($action === EntityWriteInterface::VALIDATE_ACTION_EDIT
306                            && isset($props['id'])
307                            && (int) $contextWithPath->getId() === $props['id'])) {
308                        $validator->errors()->add('urlPath', __('admin.contexts.form.pathExists'));
309                    }
310                }
311            }
312        });
313
314        // Ensure that a urlPath is not 0, because this will cause router problems
315        $validator->after(function ($validator) use ($props) {
316            if (strlen($props['urlPath'] ?? '') && !$validator->errors()->get('urlPath') && $props['urlPath'] == '0') {
317                $validator->errors()->add('urlPath', __('admin.contexts.form.pathRequired'));
318            }
319        });
320
321        // Ensure that the primary locale is one of the supported locales
322        $validator->after(function ($validator) use ($action, $props, $allowedLocales) {
323            if (isset($props['primaryLocale']) && !$validator->errors()->get('primaryLocale')) {
324                // Check against a new supported locales prop
325                if (isset($props['supportedLocales'])) {
326                    $newSupportedLocales = (array) $props['supportedLocales'];
327                    if (!in_array($props['primaryLocale'], $newSupportedLocales)) {
328                        $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
329                    }
330                    // Or check against the $allowedLocales
331                } elseif (!in_array($props['primaryLocale'], $allowedLocales)) {
332                    $validator->errors()->add('primaryLocale', __('admin.contexts.form.primaryLocaleNotSupported'));
333                }
334            }
335        });
336
337        // Ensure that the supported locales are supported by the site
338        $validator->after(function ($validator) use ($action, $props) {
339            $siteSupportedLocales = Application::get()->getRequest()->getSite()->getData('supportedLocales');
340            $localeProps = ['supportedLocales', 'supportedFormLocales', 'supportedSubmissionLocales'];
341            foreach ($localeProps as $localeProp) {
342                if (isset($props[$localeProp]) && !$validator->errors()->get($localeProp)) {
343                    $unsupportedLocales = array_diff($props[$localeProp], $siteSupportedLocales);
344                    if (!empty($unsupportedLocales)) {
345                        $validator->errors()->add($localeProp, __('api.contexts.400.localesNotSupported', ['locales' => join(__('common.commaListSeparator'), $unsupportedLocales)]));
346                    }
347                }
348            }
349        });
350
351        // If a new file has been uploaded, check that the temporary file exists and
352        // the current user owns it
353        $user = Application::get()->getRequest()->getUser();
354        ValidatorFactory::temporaryFilesExist(
355            $validator,
356            ['favicon', 'homepageImage', 'pageHeaderLogoImage', 'styleSheet'],
357            ['favicon', 'homepageImage', 'pageHeaderLogoImage'],
358            $props,
359            $allowedLocales,
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
 
360            $user ? $user->getId() : null
361        );
362
363        // If sidebar blocks are passed, ensure the block plugin exists and is
364        // enabled
365        $validator->after(function ($validator) use ($props) {
366            if (!empty($props['sidebar']) && !$validator->errors()->get('sidebar')) {
367                $plugins = PluginRegistry::loadCategory('blocks', true);
368                foreach ($props['sidebar'] as $pluginName) {
369                    if (empty($plugins[$pluginName])) {
370                        $validator->errors()->add('sidebar', __('manager.setup.layout.sidebar.invalidBlock', ['name' => $pluginName]));
371                    }
372                }
373            }
374        });
375
376        // Ensure the theme plugin is installed and enabled
377        $validator->after(function ($validator) use ($props) {
378            if (!empty($props['themePluginPath']) && !$validator->errors()->get('themePluginPath')) {
379                $plugins = PluginRegistry::loadCategory('themes', true);
380                $found = false;
381                foreach ($plugins as $plugin) {
382                    if ($props['themePluginPath'] === $plugin->getDirName()) {
383                        $found = true;
384                        break;
385                    }
386                }
387                if (!$found) {
388                    $validator->errors()->add('themePluginPath', __('manager.setup.theme.notFound'));
389                }
390            }
391        });
392
393        // Transforming copySubmissionAckAddress from CSV to array
394        $validator->after(function ($validator) use ($props) {
395            if (!isset($props['copySubmissionAckAddress'])) {
396                return;
397            }
398
399            $emails = explode(',', $props['copySubmissionAckAddress']);
400
401            if ($emails === []) {
402                return;
403            }
404
405            foreach ($emails as $currentEmail) {
406                $value = trim($currentEmail);
407
408                $emailValidator = ValidatorFactory::make(
409                    ['value' => $value],
410                    ['value' => ['email_or_localhost']]
411                );
412
413                if ($emailValidator->fails()) {
414                    $validator->errors()->add('copySubmissionAckAddress', __('manager.setup.notifications.copySubmissionAckAddress.invalid'));
415                    break;
416                }
417            }
418        });
419
420        // Only allow admins to modify which user groups are disabled for bulk emails
421        if (!empty($props['disableBulkEmailUserGroups'])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
432        if (isset($props[Context::SETTING_ENABLE_DOIS]) || isset($props[Context::SETTING_DOI_PREFIX])) {
 
443        if ($validator->fails()) {
 
447        Hook::call('Context::validate', [&$errors, $action, $props, $allowedLocales, $primaryLocale]);
448
449        return $errors;
450    }